Skip to content

feat: CUDA acceleration for Plonkish prover - #93

Merged
samuelburnham merged 6 commits into
mainfrom
sb/kzg-core
Oct 28, 2026
Merged

samuelburnham merged 6 commits into
mainfrom
sb/kzg-core

Conversation

@samuelburnham

@samuelburnham samuelburnham commented Oct 15, 2026 •

Copy link
Copy Markdown
Member

Faster Plonkish proving, CUDA offload and C++ runtime linking

Stacked on #88, which introduces the backend traits and exposes Plonkish
circuits. This PR adds the two commits on top that ix's KZG proof compression
needs from the proving core: more throughput for the Plonkish prover on the
host and on CUDA, and a native archive that links cleanly next to another
C++ runtime. The FRI protocol and proof format are unchanged.

What changes

  • Faster Plonkish proving. Parallel witness scheduling and lookup rows,
    cached hash preparation, partitioned lowering, and rejection of invalid
    challenges. Checked circuit assignments are preserved; KZG-specific code
    stays in ix.
  • CUDA offload. Host LDEs can be offloaded to auxiliary CUDA devices
    named by MULTI_STARK_CUDA_AUX_DEVICES, with mixed quotient parity
    coverage, and the sppark fork is pinned to the revision carrying the
    shared synchronization and profiling fixes. Constraint-free circuits take
    the portable quotient path instead of panicking in the device evaluator,
    extension matrices flatten without a per-element allocation, and an
    offload worker whose transform panicked drops out of the pool instead of
    poisoning later proofs.
  • CUDA archive linking. The native archive links the C++ runtime
    normally and the C adapter catches native exceptions, synchronizes
    outstanding device work on failure and returns CUDA error codes to Rust.
    Foreign static-library consumers keep its C++ ABI separate from their own
    runtime; ix's Lake build isolates it from Lean's libc++abi.

Validation

Pinned Rust formatting, CPU and CUDA clippy with warnings denied, the
portable library suite and the CUDA unit tests pass. The companion ix branch
sb/proof-compression has proved and verified a full Mathlib aggregate root
through FRI, KZG and the recursive KZG wrapper under the Filecoin powers of
tau on this core.

Review notes

  • ix pins this branch by commit and must be re-pinned to the merged head.

Comment thread src/verifier.rs Outdated
Comment thread Cargo.toml
Base automatically changed from ap/plonkish to main October 23, 2026 13:02
Carry generic proving improvements onto the public backend interfaces:
parallel witness scheduling and lookup rows, cached hash preparation,
partitioned lowering, and invalid-challenge rejection. Preserve checked
circuit assignments and keep KZG-specific implementations in ix.

Add auxiliary-device host LDEs and mixed quotient parity coverage, and pin
the sppark fork containing the shared synchronization and profiling fixes.

Constraint-free circuits take the portable quotient path instead of
panicking in the device evaluator; flatten_to_base reserves its output
once instead of allocating per element; a host-LDE worker whose offload
panicked stays out of service instead of poisoning later proofs.

Validation: pinned Rust 1.98.1 formatting and CPU/CUDA Clippy pass with
warnings denied. Focused parallel and serial CPU tests, public API tests,
and ten CUDA checks pass. Two-device checks and full suites were not run.
…rors

The Goldilocks sppark objects were compiled with SPPARK_NO_CXX_RUNTIME so
the archive carried no libstdc++ symbols into the Lean executable, which
links libc++. That left staged uploads with a hand-rolled pthread copy and
turned every native failure into an abort. Rust binaries link libstdc++
normally, and ix's Lake build now isolates the native CUDA objects together
with a private copy of the GNU runtime, so the restriction is lifted.

Staging copies go through sppark's per-device CPU workers behind
multi_stark_sppark_parallel_memcpy, which drains submitted jobs before
returning on an enqueue failure so Rust may release either buffer. Every C
entry point is noexcept and catches native exceptions at the launch
boundary, synchronizing outstanding device work before returning a CUDA
status, and the host entry points validate batch and stride bounds that
the device path already checked.

Tests cover concurrent host copies with guard bytes, rejection of invalid
buffers and shapes, and an unknown device ordinal; all 15 sppark tests and
the quotient parity tests pass on an RTX PRO 6000.
@samuelburnham
samuelburnham marked this pull request as ready for review October 27, 2026 20:01
`ByteValue` carried its nibble decomposition eagerly, so `select` paid for
the value and both nibbles: 9.5 gates per byte, with the 64 byte selects
that order a Merkle pair costing 608 of a level's 672 gates. The compact
BLAKE3 lowering reads only the value, so two thirds of that was unused in
the hashing-dominated verifier circuits.

Make the nibbles optional. Selecting between two constrained bytes yields
a value-only byte, and the paths that need nibbles (XOR, word packing,
comparisons, nibble sums) decompose and range-check them when first asked,
with the same hint and lookup constraints as before. Constructors that
already have nibbles keep them.

On a recursive FRI verifier circuit at 100 queries this takes the
translated circuit from 554k to 390k gates per query.
arthurpaulino
arthurpaulino previously approved these changes Oct 28, 2026
Comment thread benches/cuda_host_lde_bench.rs
Share fallible lookup accumulation between proving and verification while preserving public signatures. Reject zero denominators explicitly, including zero-multiplicity messages.

Pack constrained bytes directly in radix 256. Move the auxiliary CUDA host-LDE benchmark into benches and remove experimental timing runners while retaining correctness tests and reference implementations.

Validation: eight focused CPU tests passed with parallel enabled; cargo fmt --all --check, Cargo target metadata, and git diff --check passed.
@samuelburnham
samuelburnham merged commit ea4cf69 into main Oct 28, 2026
9 of 15 checks passed
@samuelburnham
samuelburnham deleted the sb/kzg-core branch October 28, 2026 15:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants